//
//  TestCT004.m
//  BookTest1
//
//  Created by IOS3 on 2018/11/7.
//  Copyright © 2018 IOS3. All rights reserved.
//

#import "TestCT004.h"
#import <CoreText/CoreText.h>


@implementation TestCT004


static CGFloat ascentCallBacks(void * ref) {
    return [(NSNumber *)[(__bridge NSDictionary *)ref valueForKey:@"height"] floatValue];
}
static CGFloat descentCallBacks(void * ref) {
    return 0;
}
static CGFloat widthCallBacks(void * ref) {
    return [(NSNumber *)[(__bridge NSDictionary *)ref valueForKey:@"width"] floatValue];
}



- (void)drawRect:(CGRect)rect {
    
    [super drawRect:rect];
    
    // 获取上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 坐标系转换, 将coreText 坐标系与UIKit对齐
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0); // 沿x轴旋转
    
    NSMutableAttributedString *mattr = [[NSMutableAttributedString alloc] initWithString:@"\n这是一段中文文字, 再加几个字母\najalkgjalngalkjn\n为什么"];
    [mattr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20] range:NSMakeRange(0, mattr.length)];
    
    
    // CTRunDelegateCallbacks 回调结构体
    CTRunDelegateCallbacks callbacks;
    // memset将已开辟内存空间 callbacks 的首 n 个字节的值设为值 0, 相当于对CTRunDelegateCallbacks内存空间初始化
    memset(&callbacks, 0, sizeof(CTRunDelegateCallbacks));
    // 设置回调版本, 下为默认
    callbacks.version = kCTRunDelegateVersion1;
    // 图片顶部距离基线的距离
    callbacks.getAscent = ascentCallBacks;
    // 图片底部距离基线的距离
    callbacks.getDescent = descentCallBacks;
    // 设置图片的宽度
    callbacks.getWidth = widthCallBacks;
    NSDictionary *picDic = @{@"height" : @140, @"width" : @60};
    CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, (__bridge void *)picDic);
    
    
    
    unichar placeHolder = 0XFFFC;
    NSString *placeHolderStr = [NSString stringWithCharacters:&placeHolder length:1];
    NSMutableAttributedString *placeHolderMattrString = [[NSMutableAttributedString alloc] initWithString:placeHolderStr];
    CFAttributedStringSetAttribute((CFMutableAttributedStringRef)placeHolderMattrString, CFRangeMake(0, 1), kCTRunDelegateAttributeName, delegate);
    CFRelease(delegate);
    
    [mattr insertAttributedString:placeHolderMattrString atIndex:18];
    
    
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mattr);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, self.bounds);
    NSInteger length = mattr.length;
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, length), path, NULL);
    CTFrameDraw(frame, context);
    
    UIImage *image = [UIImage imageWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"test001" ofType:@"png"]];
    CGRect imageFrame = [self calculateImageRectWithFrame:frame];
    CGContextDrawImage(context, imageFrame, image.CGImage);
    
    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
    
}


- (CGRect)calculateImageRectWithFrame:(CTFrameRef)frame {
    NSArray *lines = (NSArray *)CTFrameGetLines(frame);
    NSInteger count = lines.count;
    CGPoint points[count]; // ctline 起点
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), points);
    
    for (int i = 0; i < count; i++) {
        CTLineRef line = (__bridge CTLineRef)lines[i];
        // GlyphRun 高效的字符绘制方案
        NSArray *glyphRuns = (NSArray *)CTLineGetGlyphRuns(line);
        
        for (int j = 0; j < glyphRuns.count; j++) {
            CTRunRef run = (__bridge CTRunRef)glyphRuns[j];
            NSDictionary *attributes = (NSDictionary *)CTRunGetAttributes(run);
            CTRunDelegateRef delegate = (__bridge CTRunDelegateRef)[attributes valueForKey:(id)kCTRunDelegateAttributeName];
            // 只有图片设置了代理, 而e文字没有
            if (delegate == nil) {
                continue;
            }
            NSDictionary *conf = CTRunDelegateGetRefCon(delegate);
            if (![conf isKindOfClass:[NSDictionary class]]) {
                continue;
            }
            CGPoint point = points[i];
            CGFloat ascent;
            CGFloat descent;
            CGRect boundsRun;
            boundsRun.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL);
            boundsRun.size.height = ascent + descent;
            CGFloat offsetX = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
            boundsRun.origin.x = point.x + offsetX;
            boundsRun.origin.y = point.y - descent;
            
            CGPathRef path = CTFrameGetPath(frame);
            CGRect colRect = CGPathGetBoundingBox(path); // 获取剪裁区域边框
            CGRect imageBounds = CGRectOffset(boundsRun, colRect.origin.x, colRect.origin.y);
            return imageBounds;
        }
    }
    return CGRectZero;
}






//-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//    UITouch * touch = [touches anyObject];
//    // 获取点击位置的坐标
//    CGPoint location = [self systemPointFromScreenPoint:[touch locationInView:self]];
//    // 检查点击位置是否在图片上
//    if ([self checkIsClickOnImgWithPoint:location]) {
//        return;
//    }
//    [self ClickOnStrWithPoint:location];
//}
//
//-(BOOL)checkIsClickOnImgWithPoint:(CGPoint)location {
//    if ([self isFrame:_imgFrm containsPoint:location]) {
//        NSLog(@"您点击到了图片");
//        return YES;
//    }
//    return NO;
//}
//
//-(void)ClickOnStrWithPoint:(CGPoint)location {
//    NSArray * lines = (NSArray *)CTFrameGetLines(self.data.ctFrame);
//    CFRange ranges[lines.count];
//    CGPoint origins[lines.count];
//    CTFrameGetLineOrigins(_frame, CFRangeMake(0, 0), origins);
//    for (int i = 0; i < lines.count; i ++) {
//        CTLineRef line = (__bridge CTLineRef)lines[i];
//        CFRange range = CTLineGetStringRange(line);
//        ranges[i] = range;
//    }
//    for (int i = 0; i < _length; i ++) {
//        long maxLoc;
//        int lineNum;
//        for (int j = 0; j < lines.count; j ++) {
//            CFRange range = ranges[j];
//            maxLoc = range.location + range.length - 1;
//            if (i <= maxLoc) {
//                lineNum = j;
//                break;
//            }
//        }
//        CTLineRef line = (__bridge CTLineRef)lines[lineNum];        CGPoint origin = origins[lineNum];
//        CGRect CTRunFrame = [self frameForCTRunWithIndex:i CTLine:line origin:origin];
//        if ([self isFrame:CTRunFrame containsPoint:location]) {
//            NSLog(@"您点击到了第 %d 个字符，位于第 %d 行，然而他没有响应事件。",i,lineNum + 1);//点击到文字，然而没有响应的处理。可以做其他处理
//            return;
//        }
//    }
//    NSLog(@"您没有点击到文字");
//}
//
//-(BOOL)isIndex:(NSInteger)index inRange:(NSRange)range {
//    if ((index <= range.location + range.length - 1) && (index >= range.location)) {
//        return YES;
//    }
//    return NO;
//}
//
// 坐标转换
//-(CGPoint)systemPointFromScreenPoint:(CGPoint)origin {
//    return CGPointMake(origin.x, self.bounds.size.height - origin.y);
//}
//
//-(BOOL)isFrame:(CGRect)frame containsPoint:(CGPoint)point {
//    return CGRectContainsPoint(frame, point);
//}
//
//-(CGRect)frameForCTRunWithIndex:(NSInteger)index
//                         CTLine:(CTLineRef)line
//                         origin:(CGPoint)origin {
//    CGFloat offsetX = CTLineGetOffsetForStringIndex(line, index, NULL);
//    CGFloat offsexX2 = CTLineGetOffsetForStringIndex(line, index + 1, NULL);
//    offsetX += origin.x;
//    offsexX2 += origin.x;
//    CGFloat offsetY = origin.y;
//    CGFloat lineAscent;
//    CGFloat lineDescent;
//    NSArray * runs = (__bridge NSArray *)CTLineGetGlyphRuns(line);
//    CTRunRef runCurrent;
//    for (int k = 0; k < runs.count; k ++) {
//        CTRunRef run = (__bridge CTRunRef)runs[k];
//        CFRange range = CTRunGetStringRange(run);
//        NSRange rangeOC = NSMakeRange(range.location, range.length);
//        if ([self isIndex:index inRange:rangeOC]) {
//            runCurrent = run;
//            break;
//        }
//    }
//    CTRunGetTypographicBounds(runCurrent, CFRangeMake(0, 0), &lineAscent, &lineDescent, NULL);
//    CGFloat height = lineAscent + lineDescent;
//    return CGRectMake(offsetX, offsetY, offsexX2 - offsetX, height);
//}



@end
